﻿/**

 * Copyright (c) 2015-2016, FastDev 刘强 (fastdev@163.com) & Quincy.

 *

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *      http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using OF.Notify.DataHost.Cluster.Disk;
using OF.Notify.Channel;
using OF.Notify.Client;
using OF.Notify.Entity;



namespace OF.Notify.DataHost.Cluster
{
    public class ClusterContext
    {
        public int RongYu = 2;
        public int getClusterSyncNodesBatchBlockCount = 10;
        internal static ClusterContext context = null;
        internal static bool enableCountApiCall = false;
       
        public const int InvalidateId = -1;

        public static StringLock StringLock = new StringLock();

        private INotifyServiceProvider notifyServiceProvider = null;
        internal TopicInstanceProvider<TopicClusterContext> topicClusterContext = null;
        internal int maxClusterCollectionCount = Int16.MaxValue;

        internal int maxMessageCount = 1024;
        internal int maxInstantProcessCollectionCount = 1024;
        internal int processCountOnce = 1;
        internal int startupWaitProcessInterval = 5;
        internal int startupWaitSyncInterval = 5;
        internal int sendMessageRetryCount = 3;

        internal static int maxDegreeOfParallelism = 3;

        internal List<byte> allSupportedTopic;

        static ClusterContext()
        {
            context = new ClusterContext();
        }

        public static ParallelOptions GetParallelOptions()
        {
            return new ParallelOptions { MaxDegreeOfParallelism = ClusterContext.maxDegreeOfParallelism };
        }
        
        public static void SetNotifyServiceProvider(INotifyServiceProvider notifyServiceProvider)
        {
            Get().notifyServiceProvider = notifyServiceProvider;
        }

        public static ClusterContext Get()
        {
            return context;
        }

        public int GetMaxSyncTaskCount()
        {
            return 10;
        }

        public int GetMaxProcessTaskCount()
        {
            return 5;
        }

        public INotifyServiceProvider GetNotifyServiceProvider()
        {
            return notifyServiceProvider;  
        }

        public int GetProcessedMaxValue()
        {
            return int.MaxValue;
        }

        public void SetMaxClusterCollectionCount(int maxClusterCollectionCount)
        {
            this.maxClusterCollectionCount = maxClusterCollectionCount;
        }

        public int GetMaxClusterCollectionCount()
        {
            return maxClusterCollectionCount;
        }

        public void SetMaxMessageCount(int maxMessageCount)
        {
            this.maxMessageCount = maxMessageCount;
        }

        public int GetMaxMessageCount()
        {
            return maxMessageCount;
        }

        public int GetMaxRetryZookeeperCount()
        {
            return 3;
        }

        public int GetRetryFailSleepMS()
        {
            return 100;
        }

        public int GetMaxApiRetryCount()
        {
            return 3;
        }

        public void SetMaxInstantProcessCollectionCount(int maxInstantProcessCollectionCount)
        {
            this.maxInstantProcessCollectionCount = maxInstantProcessCollectionCount;
        }

        public int GetMaxInstantProcessCollectionCount()
        {
            return maxInstantProcessCollectionCount;
        }

        public void SetProcessCountOnce(int processCountOnce)
        {
            this.processCountOnce = processCountOnce;
        }

        public int GetProcessCountOnce()
        {
            return processCountOnce;
        }

        public void SetStartupWaitProcessInterval(int startupWaitProcessInterval)
        {
            this.startupWaitProcessInterval = startupWaitProcessInterval;
        }

        public int GetStartupWaitProcessInterval()
        {
            return startupWaitProcessInterval;
        }

        public void SetStartupWaitSyncInterval(int startupWaitSyncInterval)
        {
            this.startupWaitSyncInterval = startupWaitSyncInterval;
        }

        public int GetStartupWaitSyncInterval()
        {
            return startupWaitSyncInterval;
        }

        public void SetSendMessageRetryCount(int sendMessageRetryCount)
        {
            this.sendMessageRetryCount = sendMessageRetryCount;
        }

        public int GetSendMessageRetryCount()
        {
            return sendMessageRetryCount;
        }

        public void Init(Dictionary<byte, List<ConsumerBase>> topicConsumersDict)
        { 
            this.allSupportedTopic = topicConsumersDict.Keys.ToList();
            Dictionary<byte, TopicClusterContext> contextDict = new Dictionary<byte, TopicClusterContext>();
            foreach (var topicEnum in allSupportedTopic)
            {
                List<ConsumerBase> consumerList = topicConsumersDict[topicEnum];
                contextDict.Add(topicEnum, new TopicClusterContext(topicEnum, consumerList));
            }
            this.topicClusterContext = new TopicInstanceProvider<TopicClusterContext>(contextDict);
        }

        public List<byte> GetAllSupportedTopic()
        {
            return this.allSupportedTopic;
        }

        public TopicClusterContext GetTopicContext(byte topicEnum)
        {
            return topicClusterContext.GetInstance(topicEnum);
        }
    }
}
